#include "Binding.h"
#include "CsvReader.h"
#include "ClusterEdges.h"
#include "Skeleton.h"
#include "Binding.h"
#include "WrapEdges.h"
#include "FDEBCompatibility.h"  
#include "NetworkCharacteristics.h"
#include "FDEB.h"               

#include <iostream>
#include <string>

void printHelp(const char* programName);

int main(int argc, char* argv[]) {
    // Common Config
    std::string dataset;
    
    // SBEB Config
    int clusteredK = 7;                 
    int kmeansMaxIterations = 100;   
    double maxSkeletonSegmentLength = 10.0; 
    int warpSegments = 20;            
    double warpAlpha = 0.1;               

    // FDEB Config
    int initialSubdivisionPoints = 1;  
    double compatibilityThreshold = 0.85;  
    
    int fdebPhases = 2;               
    int iterationsPerPhase = 50;      
    double forceStepSize = 0.1;      
 

    // 解析命令行参数
    for (int i = 1; i < argc; ++i) {
        std::string arg = argv[i];
        
        if (arg == "--help" || arg == "-h") {
            printHelp(argv[0]);
            return 0;
        }
        else if (arg == "--dataset" && i + 1 < argc) {
            dataset = argv[++i];
        }
        else if (arg == "--clusteredK" && i + 1 < argc) {
            clusteredK = std::atoi(argv[++i]);
        }
        else if (arg == "--kmeansMaxIter" && i + 1 < argc) {
            kmeansMaxIterations = std::atoi(argv[++i]);
        }
        else if (arg == "--maxSkeletonLen" && i + 1 < argc) {
            maxSkeletonSegmentLength = std::atof(argv[++i]);
        }
        else if (arg == "--warpSegments" && i + 1 < argc) {
            warpSegments = std::atoi(argv[++i]);
        }
        else if (arg == "--warpAlpha" && i + 1 < argc) {
            warpAlpha = std::atof(argv[++i]);
        }
        else if (arg == "--initSubdivPoints" && i + 1 < argc) {
            initialSubdivisionPoints = std::atoi(argv[++i]);
        }
        else if (arg == "--compatThreshold" && i + 1 < argc) {
            compatibilityThreshold = std::atof(argv[++i]);
        }
        else if (arg == "--fdebPhases" && i + 1 < argc) {
            fdebPhases = std::atoi(argv[++i]);
        }
        else if (arg == "--iterPerPhase" && i + 1 < argc) {
            iterationsPerPhase = std::atoi(argv[++i]);
        }
        else if (arg == "--forceStepSize" && i + 1 < argc) {
            forceStepSize = std::atof(argv[++i]);
        }
        else {
            std::cerr << "Unknown option or missing argument: " << arg << std::endl;
            printHelp(argv[0]);
            return 1;
        }
    }

    if (dataset.empty()) {
        std::cerr << "Error: Dataset parameter is required!" << std::endl;
        printHelp(argv[0]);
        return 1;
    }

    try {
        // 1. Load csv
        auto graph = readGraphData(dataset + "/nodes.csv", 
                                   dataset + "/edges.csv");
        std::cout << "Loaded " << graph.nodes.size() << " nodes and "
                  << graph.edges.size() << " edges." << std::endl;

        // 2. 聚类边
        auto clusteredEdges = clusterEdges(graph.edges, graph.nodes, clusteredK, kmeansMaxIterations);
        std::cout << "Clustering complete. Generated " << clusteredEdges.size()
                  << " clusters." << std::endl;
        write_clustered_edges_to_csv(clusteredEdges, dataset + "/gen_clustered_edges.csv");

        // 4. 提取骨架线段
        auto skeletons = extractSkeleton(clusteredEdges, graph.nodes, maxSkeletonSegmentLength);
        std::cout << "Skeleton extraction complete." << std::endl;

        // 5. 写入骨架线段到 CSV
        writeSkeletonToCsv(skeletons, dataset + "/gen_skeleton_edges.csv");
        std::cout << "Skeleton written to CSV." << std::endl;

        // 6. 计算绑定信息
        auto bindings = computeBindings(graph.nodes, skeletons, clusteredEdges, 8, 0.1);
        std::cout << "Binding complete. Computed " << bindings.size() << " bindings." << std::endl;

        // 7. WrapEdges
        auto warpedEdges = warpEdges(bindings, graph.nodes, warpSegments, warpAlpha);
        writeWarpedEdgesToCsv(warpedEdges, bindings, dataset + "/gen_warped_edges.csv");

        // 8. FDEB
        auto fdebEdges = buildFDEBEdges(graph.edges, graph.nodes, initialSubdivisionPoints);
        std::cout << "Built " << fdebEdges.size() << " FDEB edges." << std::endl;
        
        buildCompatibilityLists(fdebEdges, compatibilityThreshold);
        std::cout << "Built compatibility lists." << std::endl;

        FDEBOptions opts;
        opts.K = fdebPhases;   
        opts.C = iterationsPerPhase;   
        opts.S = forceStepSize; 

        runFDEB(fdebEdges, opts);
        std::cout << "FDEB algorithm completed." << std::endl;
        writeBundledEdgesToCSV(fdebEdges, dataset + "/gen_fdeb_edges.csv");
        
        // 9. Network Chars
        NetworkCharacteristics stats = computeNetworkCharacteristics(graph.nodes, graph.edges);
        writeNetworkCharacteristicsToCsv(stats, dataset + "/gen_networkchars.csv");

        std::cout << "Network Characteristics written to CSV." << std::endl;


    } catch (const std::exception& e) {
        std::cerr << "Error: " << e.what() << std::endl;
    }

    return 0;
}

void printHelp(const char* programName) {
    std::cout << "Usage: " << programName << " --dataset <name> [options]" << std::endl;
    std::cout << "Required:" << std::endl;
    std::cout << "  --dataset <name>            Dataset name (required, no default)" << std::endl;
    std::cout << "SBEB Parameters:" << std::endl;
    std::cout << "  --clusteredK <num>          Number of clusters (default: 7)" << std::endl;
    std::cout << "  --kmeansMaxIter <num>       Max iterations for KMeans (default: 100)" << std::endl;
    std::cout << "  --maxSkeletonLen <value>    Max skeleton segment length (default: 10.0)" << std::endl;
    std::cout << "  --warpSegments <num>        Number of warp segments (default: 20)" << std::endl;
    std::cout << "  --warpAlpha <value>         Warp alpha coefficient (default: 0.1)" << std::endl;
    std::cout << "FDEB Parameters:" << std::endl;
    std::cout << "  --initSubdivPoints <num>    Initial subdivision points (default: 1)" << std::endl;
    std::cout << "  --compatThreshold <value>   Compatibility threshold (default: 0.85)" << std::endl;
    std::cout << "  --fdebPhases <num>          FDEB phases (default: 2)" << std::endl;
    std::cout << "  --iterPerPhase <num>        Iterations per phase (default: 50)" << std::endl;
    std::cout << "  --forceStepSize <value>     Force step size (default: 0.1)" << std::endl;
    std::cout << "  --help, -h                  Show this help message" << std::endl;
}